﻿using Payroll.Biz.Legacy.DAL;
using Payroll.Biz.Legacy.Models;
using Payroll.Biz.Legacy.ServiceParams;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Payroll.Biz.Legacy.Services
{
    public class CalculatePayService : AbstractService, IService<CalculatePayServiceParams>
    {
        public CalculatePayService(IPayrollDatabase database) : base(database)
        {
        }

        public ServiceResult Execute(CalculatePayServiceParams serviceParams)
        {
            IList<Guid> employeeIds = Database.GetAllEmployeeIds();

            IList<Paycheck> result = new List<Paycheck>();

            foreach (Guid employeeId in employeeIds)
            {
                Employee employee = Database.GetEmployee(employeeId);
                if ((employee != null) && employee.IsPayDate(serviceParams.PayDate))
                {
                    DateTime startDate = employee.GetPayPeriodStartDate(serviceParams.PayDate);

                    Range<DateTime> dateRange = new Range<DateTime> { From = startDate, To = serviceParams.PayDate };

                    switch (employee.Classification)
                    {
                        // Load time cards for hourly based employees
                        case HourlyClassification _:
                            LoadTimeCards(employee, dateRange);

                            break;
                        // Load sales receipts for commission based employees
                        case CommissionClassification _:
                            LoadSalesReceipts(employee, dateRange);

                            break;
                    }

                    // Load service charges for union members
                    if (employee.Affiliation is UnionAffiliation)
                    {
                        LoadServiceCharges(employee, dateRange);
                    }

                    Paycheck paycheck = new Paycheck(startDate, serviceParams.PayDate);

                    employee.Payday(paycheck);

                    result.Add(paycheck);
                }
            }

            return ServiceResult.CreateSuccessResult(result);
        }

        private void LoadServiceCharges(Employee employee, Range<DateTime> dateRange)
        {
            IList<ServiceCharge> serviceCharges = Database.GetEmployeeServiceCharges(employee.Id, dateRange);

            UnionAffiliation affiliation = (UnionAffiliation)employee.Affiliation;

            foreach (ServiceCharge sc in serviceCharges)
            {
                affiliation.AddServiceCharge(sc);
            }
        }

        private void LoadSalesReceipts(Employee employee, Range<DateTime> dateRange)
        {
            IList<SalesReceipt> salesReceipts = Database.GetEmployeeSalesReceipts(employee.Id, dateRange);

            CommissionClassification classification = (CommissionClassification)employee.Classification;

            foreach (SalesReceipt sr in salesReceipts)
            {
                classification.AddSalesReceipt(sr);
            }
        }

        private void LoadTimeCards(Employee employee, Range<DateTime> dateRange)
        {
            IList<TimeCard> timeCards = Database.GetEmployeeTimeCards(employee.Id, dateRange);

            HourlyClassification classification = (HourlyClassification)employee.Classification;
            foreach (TimeCard tc in timeCards)
            {
                classification.AddTimeCard(tc);
            }
        }
    }
}
